home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / Delphi 3.0 / DATA.Z / copyprsr.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-01-29  |  9.5 KB  |  413 lines

  1. unit CopyPrsr;
  2.  
  3. interface
  4.  
  5. uses Classes;
  6.  
  7. const
  8.   toEOL = Char(5);
  9.  
  10. type
  11. { TCopyParser }
  12.  
  13.   TCopyParser = class(TObject)
  14.   private
  15.     FStream: TStream;
  16.     FOutStream: TStream;
  17.     FOrigin: Longint;
  18.     FBuffer: PChar;
  19.     FBufPtr: PChar;
  20.     FBufEnd: PChar;
  21.     FSourcePtr: PChar;
  22.     FSourceEnd: PChar;
  23.     FTokenPtr: PChar;
  24.     FStringPtr: PChar;
  25.     FSourceLine: Integer;
  26.     FSaveChar: Char;
  27.     FToken: Char;
  28.     procedure ReadBuffer;
  29.     procedure SkipBlanks(DoCopy: Boolean);
  30.     function SkipToNextToken(CopyBlanks, DoCopy: Boolean): Char;
  31.     function CopySkipTo(Length: Integer; DoCopy: Boolean): string;
  32.     function CopySkipToToken(AToken: Char; DoCopy: Boolean): string;
  33.     function CopySkipToEOL(DoCopy: Boolean): string;
  34.     function CopySkipToEOF(DoCopy: Boolean): string;
  35.     procedure UpdateOutStream(StartPos: PChar);
  36.   public
  37.     constructor Create(Stream, OutStream: TStream);
  38.     destructor Destroy; override;
  39.     procedure CheckToken(T: Char);
  40.     procedure CheckTokenSymbol(const S: string);
  41.     function CopyTo(Length: Integer): string;
  42.     function CopyToToken(AToken: Char): string;
  43.     function CopyToEOL: string;
  44.     function CopyToEOF: string;
  45.     procedure CopyTokenToOutput;
  46.     procedure Error(const Ident: string);
  47.     procedure ErrorFmt(const Ident: string; const Args: array of const);
  48.     procedure ErrorStr(const Message: string);
  49.     function NextToken: Char;
  50.     function SkipToken(CopyBlanks: Boolean): Char;
  51.     procedure SkipEOL;
  52.     function SkipTo(Length: Integer): string;
  53.     function SkipToToken(AToken: Char): string;
  54.     function SkipToEOL: string;
  55.     function SkipToEOF: string;
  56.     function SourcePos: Longint;
  57.     function TokenComponentIdent: String;
  58.     function TokenFloat: Extended;
  59.     function TokenInt: Longint;
  60.     function TokenString: string;
  61.     function TokenSymbolIs(const S: string): Boolean;
  62.     property SourceLine: Integer read FSourceLine;
  63.     property Token: Char read FToken;
  64.   end;
  65.  
  66. implementation
  67.  
  68. uses SysUtils, Consts;
  69.  
  70. { TCopyParser }
  71.  
  72. const
  73.   ParseBufSize = 4096;
  74.  
  75. constructor TCopyParser.Create(Stream, OutStream: TStream);
  76. begin
  77.   FStream := Stream;
  78.   FOutStream := OutStream;
  79.   GetMem(FBuffer, ParseBufSize);
  80.   FBuffer[0] := #0;
  81.   FBufPtr := FBuffer;
  82.   FBufEnd := FBuffer + ParseBufSize;
  83.   FSourcePtr := FBuffer;
  84.   FSourceEnd := FBuffer;
  85.   FTokenPtr := FBuffer;
  86.   FSourceLine := 1;
  87.   SkipToken(True);
  88. end;
  89.  
  90. destructor TCopyParser.Destroy;
  91. begin
  92.   if FBuffer <> nil then
  93.   begin
  94.     FStream.Seek(Longint(FTokenPtr) - Longint(FBufPtr), 1);
  95.     FreeMem(FBuffer, ParseBufSize);
  96.   end;
  97. end;
  98.  
  99. procedure TCopyParser.CheckToken(T: Char);
  100. begin
  101.   if Token <> T then
  102.     case T of
  103.       toSymbol:
  104.         Error(SIdentifierExpected);
  105.       toString:
  106.         Error(SStringExpected);
  107.       toInteger, toFloat:
  108.         Error(SNumberExpected);
  109.     else
  110.       ErrorFmt(SCharExpected, [T]);
  111.     end;
  112. end;
  113.  
  114. procedure TCopyParser.CheckTokenSymbol(const S: string);
  115. begin
  116.   if not TokenSymbolIs(S) then ErrorFmt(SSymbolExpected, [S]);
  117. end;
  118.  
  119. function TCopyParser.CopySkipTo(Length: Integer; DoCopy: Boolean): string;
  120. var
  121.   P: PChar;
  122.   Temp: string;
  123. begin
  124.   Result := '';
  125.   repeat
  126.     P := FTokenPtr;
  127.     while (Length > 0) and (P^ <> #0) do
  128.     begin
  129.       Inc(P);
  130.       Dec(Length);
  131.     end;
  132.     if DoCopy and (FOutStream <> nil) then
  133.         FOutStream.WriteBuffer(FTokenPtr^, P - FTokenPtr);
  134.     SetString(Temp, FTokenPtr, P - FTokenPtr);
  135.     Result := Result + Temp;
  136.     if Length > 0 then ReadBuffer;
  137.   until (Length = 0) or (Token = toEOF);
  138.   FSourcePtr := P;
  139. end;
  140.  
  141. function TCopyParser.CopySkipToEOL(DoCopy: Boolean): string;
  142. var
  143.   P: PChar;
  144. begin
  145.   P := FTokenPtr;
  146.   while not (P^ in [#13, #10, #0]) do Inc(P);
  147.   SetString(Result, FTokenPtr, P - FTokenPtr);
  148.   if P^ = #13 then Inc(P);
  149.   FSourcePtr := P;
  150.   if DoCopy then UpdateOutStream(FTokenPtr);
  151.   NextToken;
  152. end;
  153.  
  154. function TCopyParser.CopySkipToEOF(DoCopy: Boolean): string;
  155. var
  156.   P: PChar;
  157.   Temp: string;
  158. begin
  159.   repeat
  160.     P := FTokenPtr;
  161.     while P^ <> #0 do Inc(P);
  162.     FSourcePtr := P;
  163.     ReadBuffer;
  164.     SetString(Temp, FTokenPtr, P - FTokenPtr);
  165.     Result := Result + Temp;
  166.     if DoCopy then
  167.     begin
  168.       UpdateOutStream(FTokenPtr);
  169.       NextToken;
  170.     end else SkipToken(False);
  171.   until Token = toEOF;
  172. end;
  173.  
  174. function TCopyParser.CopySkipToToken(AToken: Char; DoCopy: Boolean): string;
  175. var
  176.   S: PChar;
  177.   Temp: string;
  178. begin
  179.   Result := '';
  180.   while (Token <> AToken) and (Token <> toEOF) do
  181.   begin
  182.     S := FSourcePtr;
  183.     SkipBlanks(DoCopy);
  184.     if S <> FSourcePtr then
  185.     begin
  186.       SetString(Temp, S, FSourcePtr - S);
  187.       Result := Result + Temp;
  188.     end;
  189.     SkipToNextToken(DoCopy, DoCopy);
  190.     if Token <> AToken then
  191.     begin
  192.       SetString(Temp, FTokenPtr, FSourcePtr - FTokenPtr);
  193.       Result := Result + Temp;
  194.     end;
  195.   end;
  196. end;
  197.  
  198. function TCopyParser.CopyTo(Length: Integer): string;
  199. begin
  200.   Result := CopySkipTo(Length, True);
  201. end;
  202.  
  203. function TCopyParser.CopyToToken(AToken: Char): string;
  204. begin
  205.   Result := CopySkipToToken(AToken, True);
  206. end;
  207.  
  208. function TCopyParser.CopyToEOL: string;
  209. begin
  210.   Result := CopySkipToEOL(True);
  211. end;
  212.  
  213. function TCopyParser.CopyToEOF: string;
  214. begin
  215.   Result := CopySkipToEOF(True);
  216. end;
  217.  
  218. procedure TCopyParser.CopyTokenToOutput;
  219. begin
  220.   UpdateOutStream(FTokenPtr);
  221. end;
  222.  
  223. procedure TCopyParser.Error(const Ident: string);
  224. begin
  225.   ErrorStr(Ident);
  226. end;
  227.  
  228. procedure TCopyParser.ErrorFmt(const Ident: string; const Args: array of const);
  229. begin
  230.   ErrorStr(Format(Ident, Args));
  231. end;
  232.  
  233. procedure TCopyParser.ErrorStr(const Message: string);
  234. begin
  235.   raise EParserError.CreateFmt(SParseError, [Message, FSourceLine]);
  236. end;
  237.  
  238. function TCopyParser.NextToken: Char;
  239. begin
  240.   Result := SkipToNextToken(True, True);
  241. end;
  242.  
  243. function TCopyParser.SkipTo(Length: Integer): string;
  244. begin
  245.   Result := CopySkipTo(Length, False);
  246. end;
  247.  
  248. function TCopyParser.SkipToToken(AToken: Char): string;
  249. begin
  250.   Result := CopySkipToToken(AToken, False);
  251. end;
  252.  
  253. function TCopyParser.SkipToEOL: string;
  254. begin
  255.   Result := CopySkipToEOL(False);
  256. end;
  257.  
  258. function TCopyParser.SkipToEOF: string;
  259. begin
  260.   Result := CopySkipToEOF(False);
  261. end;
  262.  
  263. function TCopyParser.SkipToNextToken(CopyBlanks, DoCopy: Boolean): Char;
  264. var
  265.   P, StartPos: PChar;
  266. begin
  267.   SkipBlanks(CopyBlanks);
  268.   P := FSourcePtr;
  269.   FTokenPtr := P;
  270.   case P^ of
  271.     'A'..'Z', 'a'..'z', '_':
  272.       begin
  273.         Inc(P);
  274.         while P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_'] do Inc(P);
  275.         Result := toSymbol;
  276.       end;
  277.     #10:
  278.       begin
  279.         Inc(P);
  280.         Inc(FSourceLine);
  281.         Result := toEOL;
  282.       end;
  283.   else
  284.     Result := P^;
  285.     if Result <> toEOF then Inc(P);
  286.   end;
  287.   StartPos := FSourcePtr;
  288.   FSourcePtr := P;
  289.   if DoCopy then UpdateOutStream(StartPos);
  290.   FToken := Result;
  291. end;
  292.  
  293. function TCopyParser.SkipToken(CopyBlanks: Boolean): Char;
  294. begin
  295.   Result := SkipToNextToken(CopyBlanks, False);
  296. end;
  297.  
  298. procedure TCopyParser.ReadBuffer;
  299. var
  300.   Count: Integer;
  301. begin
  302.   Inc(FOrigin, FSourcePtr - FBuffer);
  303.   FSourceEnd[0] := FSaveChar;
  304.   Count := FBufPtr - FSourcePtr;
  305.   if Count <> 0 then Move(FSourcePtr[0], FBuffer[0], Count);
  306.   FBufPtr := FBuffer + Count;
  307.   Inc(FBufPtr, FStream.Read(FBufPtr[0], FBufEnd - FBufPtr));
  308.   FSourcePtr := FBuffer;
  309.   FSourceEnd := FBufPtr;
  310.   if FSourceEnd = FBufEnd then
  311.   begin
  312.     FSourceEnd := LineStart(FBuffer, FSourceEnd - 1);
  313.     if FSourceEnd = FBuffer then Error(SLineTooLong);
  314.   end;
  315.   FSaveChar := FSourceEnd[0];
  316.   FSourceEnd[0] := #0;
  317. end;
  318.  
  319. procedure TCopyParser.SkipBlanks(DoCopy: Boolean);
  320. var
  321.   Start: PChar;
  322. begin
  323.   Start := FSourcePtr;
  324.   while True do
  325.   begin
  326.     case FSourcePtr^ of
  327.       #0:
  328.         begin
  329.           if DoCopy then UpdateOutStream(Start);
  330.           ReadBuffer;
  331.           if FSourcePtr^ = #0 then Exit;
  332.           Start := FSourcePtr;
  333.           Continue;
  334.         end;
  335.       #10:
  336.         Inc(FSourceLine);
  337.       #33..#255:
  338.         Break;
  339.     end;
  340.     Inc(FSourcePtr);
  341.   end;
  342.   if DoCopy then UpdateOutStream(Start);
  343. end;
  344.  
  345. function TCopyParser.SourcePos: Longint;
  346. begin
  347.   Result := FOrigin + (FTokenPtr - FBuffer);
  348. end;
  349.  
  350. procedure TCopyParser.SkipEOL;
  351. begin
  352.   if Token = toEOL then
  353.   begin
  354.     while FTokenPtr^ in [#13, #10] do Inc(FTokenPtr);
  355.     FSourcePtr := FTokenPtr;
  356.     if FSourcePtr^ <> #0 then
  357.       NextToken
  358.     else FToken := #0;
  359.   end;
  360. end;
  361.  
  362. function TCopyParser.TokenFloat: Extended;
  363. begin
  364.   Result := StrToFloat(TokenString);
  365. end;
  366.  
  367. function TCopyParser.TokenInt: Longint;
  368. begin
  369.   Result := StrToInt(TokenString);
  370. end;
  371.  
  372. function TCopyParser.TokenString: string;
  373. var
  374.   L: Integer;
  375. begin
  376.   if FToken = toString then
  377.     L := FStringPtr - FTokenPtr else
  378.     L := FSourcePtr - FTokenPtr;
  379.   SetString(Result, FTokenPtr, L);
  380. end;
  381.  
  382. function TCopyParser.TokenSymbolIs(const S: string): Boolean;
  383. begin
  384.   Result := (Token = toSymbol) and (CompareText(S, TokenString) = 0);
  385. end;
  386.  
  387. function TCopyParser.TokenComponentIdent: String;
  388. var
  389.   P: PChar;
  390. begin
  391.   CheckToken(toSymbol);
  392.   P := FSourcePtr;
  393.   while P^ = '.' do
  394.   begin
  395.     Inc(P);
  396.     if not (P^ in ['A'..'Z', 'a'..'z', '_']) then
  397.       Error(SIdentifierExpected);
  398.     repeat
  399.       Inc(P)
  400.     until not (P^ in ['A'..'Z', 'a'..'z', '0'..'9', '_']);
  401.   end;
  402.   FSourcePtr := P;
  403.   Result := TokenString;
  404. end;
  405.  
  406. procedure TCopyParser.UpdateOutStream(StartPos: PChar);
  407. begin
  408.   if FOutStream <> nil then
  409.     FOutStream.WriteBuffer(StartPos^, FSourcePtr - StartPos);
  410. end;
  411.  
  412. end.
  413.